home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / BG_SRC.ZIP / BG_GENES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-31  |  8.6 KB  |  297 lines

  1. /*
  2.  *
  3.  *                            B G_ G E N E S . C
  4.  * O.F.Ransen:    15th April 1992
  5.  * This version:  12th Feb   1993
  6.  * This file deals with selecting the best players and changing the
  7.  * strategy weightings of the worst one. This is in the hope that the
  8.  * worse ones 'learn' to become better. The strategic weightings are
  9.  * stored in a file.
  10.  *
  11.  */
  12.  
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <conio.h>
  18. #include <dos.h>
  19. #include "bg.h"
  20.  
  21. /**************************************************************************/
  22.  
  23. const short N_Times = 5 ; /* How many tournaments */
  24. extern int Target_Score ; /* To what level */
  25.  
  26. extern long Weights [N_OPPS][N_WEIGHTS] ;
  27.  
  28. const short Pos_Change [N_OPPS] = {0,5,10,20} ;
  29.     /* The further down we go in the classification the more drastic the
  30.     changes need to be to get something going. A P at the top of the
  31.     classification has a 0% change coz he is doing well, so he changes
  32.     nothing in his strategy */
  33.  
  34. #define WF_NAME "WEIGHTS.C"
  35.  
  36. /***************************************************************************/
  37.  
  38. void Genetic_Selection (void)
  39. /*
  40. PURPOSE: To run several tournaments between the computer players. The
  41. winner of the tournament does not have his weights adjusted, while the
  42. losers do.
  43. */
  44. {                              /* Piero, Sergio, Enzo, Antonello */
  45.     short Positions [N_OPPS] ; /* [THIRD,FIRST,LAST,SECOND] */
  46.     short Old_Positions [N_OPPS] ;
  47.     short Deltas [N_OPPS][N_WEIGHTS] ;
  48.     short p,t;
  49.  
  50.     Read_Weights (Weights) ;
  51.  
  52.     Target_Score = 7 ;
  53.     t = 0 ;
  54.     for (p = 0 ; p < N_OPPS ; p++) {
  55.         Positions[p] = p ; /* Initialised, but no real meaning yet */
  56.     }
  57.  
  58.     Print_Tournament (t,Positions) ;
  59.  
  60.     t = 1 ;
  61.     Tournament (Positions) ; /* Get an initial classification */
  62.     Print_Tournament (t,Positions) ;
  63.  
  64.     /* Randomise the initial changes */
  65.     for (p = 0 ; p < N_OPPS ; p++) {
  66.         Randomise_Deltas (Deltas[p],Positions[p]) ;
  67.     }
  68.  
  69.     for (t = 2 ; t < N_Times ; t++) {
  70.  
  71.         for (p = 0 ; p < N_OPPS ; p++) {        /* Store old pos so we can */
  72.             Old_Positions [p] = Positions [p] ; /* do a comparison later   */
  73.         }
  74.  
  75.         /* Change weights by deltas */
  76.         for (p = 0 ; p < N_OPPS ; p++) {
  77.            Remake_Weights (Weights[p],Deltas[p]) ;
  78.         }
  79.  
  80.         Print_Tournament (t,Positions) ;
  81.         /* Have another go */
  82.         Tournament (Positions) ;
  83.  
  84.         for (p = 0 ; p < N_OPPS ; p++) {
  85.             /* If position is better reinforce the weight change */
  86.             Reinforce_Or_Shuffle (Deltas[p],Positions[p],Old_Positions[p]) ;
  87.         }
  88.     }
  89.  
  90.     Write_Weights (Weights,Positions) ;
  91.     printf ("\nFinished games") ; (void)getch () ;
  92.     Go_Text_Mode () ;
  93. }
  94.  
  95. /***************************************************************************/
  96.  
  97. void Read_Weights (long Weights[N_OPPS][N_WEIGHTS])
  98. /*
  99. PURPOSE: To read the weights of the players from a file called WEIGHTS.C.
  100. The file is roughly in C code format so it can be easily incorportated
  101. into in the program.
  102. */
  103. {
  104.     FILE* File ;
  105.     short p, w ;
  106.     boolean Error = FALSE ;
  107.  
  108.     File = fopen (WF_NAME,"rt") ;
  109.  
  110.     if (File != NULL) {
  111.         for (p = 0 ; p < N_OPPS ; p++) {
  112.             if (fscanf (File,"{%ld",&Weights[p][0]) != 1) {
  113.                 Error = TRUE ;
  114.                 break ;
  115.             }
  116.             for (w = 1 ; w < N_WEIGHTS ; w++) {
  117.                 if (fscanf (File,",%ld",&Weights[p][w]) != 1) {
  118.                     Error = TRUE ;
  119.                     break ;
  120.                 }
  121.             }
  122.             fscanf (File,"},\n") ;
  123.             if (Error) {
  124.                 break ;
  125.             }
  126.         }
  127.         fclose (File) ;
  128.         if (Error) {
  129.             printf ("\nError reading %s, using predefined values",WF_NAME) ;
  130.         }
  131.     }
  132. }
  133.  
  134. /***************************************************************************/
  135.  
  136. void Write_Weights (long Weights [N_OPPS][N_WEIGHTS], short Positions[N_OPPS])
  137. /*
  138. PURPOSE: To write out the weights as a C array of N_OPPS rows by
  139.          N_WEIGHTS columns. We also write out the classifications as
  140.          passed to us in Positions.
  141. */
  142. {
  143.     FILE* File ;
  144.     extern String_Menu_t Setup_Menu [N_SETUP_FIELDS] ;
  145.     short p, w ;
  146.  
  147.     File = fopen (WF_NAME,"wt") ;
  148.  
  149.     if (File == NULL) {
  150.         printf ("\nSERIOUS ERROR: Cannot open %s for writing",WF_NAME) ;
  151.         return ;
  152.     }
  153.  
  154.     for (p = 0 ; p < N_OPPS ; p++) {
  155.         fprintf (File,"{%5ld",Weights[p][0]) ;
  156.         for (w = 1 ; w < N_WEIGHTS ; w++) {
  157.             fprintf (File,",%4ld",Weights[p][w]) ;
  158.         }
  159.         fprintf (File,"},\n") ;
  160.     }
  161.  
  162.     for (p = 0 ; p < N_OPPS ; p++) {
  163.         fprintf (File,"\n/* %s(#%d) finished in position %d */ ",
  164.                  Setup_Menu[OPP_FIELD].Options[0][p], // Name of player
  165.                  p,                                   // Number of player
  166.                  Positions[p])  ;                     // Position of player
  167.     }
  168.     fclose (File) ;
  169. }
  170.  
  171. /***************************************************************************/
  172.  
  173. void Reinforce_Or_Shuffle (short Deltas[N_WEIGHTS], short Pos, short Old_Pos)
  174. /*
  175. If the Pos is better than the Old_Pos then Deltas do not change coz
  176. we are going in the right direction. If it is equal or worse then we
  177. change the deltas in random directions by an amount which increases
  178. with worsening Pos. The idea is that the worse the position the more
  179. drastic the change needs to be, so Pos_Change is a list of increasing
  180. percentage values.
  181. */
  182. {
  183.     if (Pos >= Old_Pos) { /* Lower down in classification, so shuffle */
  184.         Randomise_Deltas (Deltas,Pos) ;
  185.     }
  186. }
  187.  
  188. /***************************************************************************/
  189.  
  190. void Remake_Weights (long Weights[N_WEIGHTS], short Deltas[N_WEIGHTS])
  191. /*
  192. PURPOSE: To add the deltas to the weights, limiting the resulting
  193. weights from 0..100 inclusive.
  194. */
  195. {
  196.     short w ;
  197.  
  198.     for (w = 0 ; w < N_WEIGHTS ; w++) {
  199.         Weights[w] = Weights[w] + Deltas[w] ;
  200.         if (Weights[w] < 0) {
  201.             Weights[w] = 0 ;
  202.         } else if (Weights[w] > 100) {
  203.             Weights[w] = 100 ;
  204.         }
  205.     }
  206. }
  207.  
  208. /***************************************************************************/
  209.  
  210. void Tournament (short Pos[N_OPPS])
  211. /*
  212. PURPOSE: To run a tournament between all the players. Then the
  213. classification of each player is stored in Pos. e.g:
  214.     Player_Name =  Piero, Sergio, Enzo, Antonello
  215.                 =      0,     1,     2,      3
  216.     Player_Pos  = {THIRD, FIRST,  LAST, SECOND}
  217.                 = {    2,     0,     3,      1}
  218. */
  219. {
  220.     short w,b,p,i,q,Winnr,Temp;
  221.     short Wins[N_OPPS],Ply[N_OPPS] ;
  222.  
  223.     for (p = 0 ; p < N_OPPS ; p++) {
  224.         Wins[p] = 0 ;
  225.         Ply[p]  = p ;
  226.     }
  227.  
  228.     for (b = 0 ; b < N_OPPS-1 ; b++) {       /* b=0..N_OPPS-2   */
  229.         for (w = b+1 ; w < N_OPPS ; w++) {   /* w=b+1..N_OPPS-1 */
  230.             Winnr = Get_Winner (b,w) ;
  231.             Wins [Winnr]++ ;
  232.         }
  233.     }
  234.  
  235.     for (q = 0 ; q < N_OPPS ; q++) {
  236.         for (p = 0 ; p < N_OPPS-2 ; p++) {
  237.             if (Wins[p] < Wins[p+1]) {
  238.                 Temp      = Wins[p] ;
  239.                 Wins[p]   = Wins[p+1] ;
  240.                 Wins[p+1] = Temp ;
  241.                 Temp      = Ply[p] ;
  242.                 Ply[p]    = Ply[p+1] ;
  243.                 Ply[p+1]  = Temp ;
  244.             }
  245.         }
  246.     }
  247.  
  248.     for (i = 0 ; i < N_OPPS ; i++) {
  249.         Pos [Ply[i]] = i ;
  250.     }
  251.  
  252. }
  253.  
  254. /***************************************************************************/
  255.  
  256. void Randomise_Deltas (short Deltas[N_WEIGHTS], short Position)
  257. {
  258.     short w ;
  259.     for (w = 0 ; w < N_WEIGHTS ; w++) {
  260.         if (rand()&1) {
  261.             Deltas[w] =  Pos_Change [Position] ;
  262.         } else {
  263.             Deltas[w] = -Pos_Change [Position] ;
  264.         }
  265.     }
  266. }
  267.  
  268. /***************************************************************************/
  269.  
  270. short Get_Winner (short Black, short White)
  271. {
  272.     extern Stats_t Statistics[N_PLAYERS] ;
  273.     boolean Playing ;
  274.  
  275.     if ((Black < 0) || (White < 0) ||
  276.         (Black >= N_OPPS) || (White >= N_OPPS)) {
  277.         printf ("\nBlack = %d, White = %d",Black,White) ;
  278.         Error_Exit ("Bad players in tournament!") ;
  279.     }
  280.  
  281.     Init_Stats () ;
  282.     Init_Genetic_Opponents (Black,White) ;
  283.     Print_Opponents (Black,White) ;
  284.  
  285.     do {
  286.         Playing = Play_The_Game (MED_SPEED,NULL_PLAYER,Black);
  287.     } while (Playing) ;
  288.  
  289.     if (Statistics[BLACK_PLAYER].Games_Won >= Target_Score) {
  290.         return (Black) ;
  291.     } else {
  292.         return (White) ;
  293.     }
  294. }
  295.  
  296. /***************************************************************************/
  297.